/*
 * Copyright (C) 2019 ByteDance Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bytedance.scene.view;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.StackLayout;
import ohos.app.Context;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

/**
 * Created by JiangQi on 8/9/18.
 */
public class SlidePercentFrameLayout extends StackLayout implements Component.TouchEventListener {

    public static interface Callback {

        boolean isSupport();

        void onStart();

        void onFinish();

        void onProgress(float progress);
    }

    private static final int EDGE_SIZE = 50; // dp
    private boolean mSwipeEnabled = true;
    private Callback mCallback;
    private int mEdgeSize;
    private float mInitRawX;
    private float mInterceptInitX;
    private int mLastMotionX;
    private int mTouchSlop = 0;
    private boolean mIsBeingDragged = false;
    private int mActivePointerId = INVALID_POINTER;
    private static final int INVALID_POINTER = -1;
    private boolean mSkipUntilNextGestureEvent = false;

    public SlidePercentFrameLayout(Context context) {
        this(context, null);
    }

    public SlidePercentFrameLayout(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public SlidePercentFrameLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setTouchEventListener(this);
        init();
    }


    private void init() {
        mEdgeSize = AttrHelper.vp2px(EDGE_SIZE, getContext());
        setTouchEventListener(this);
    }

    public void setCallback(Callback callback) {
        this.mCallback = callback;
    }


    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {


        if (this.mCallback == null || this.mSkipUntilNextGestureEvent || !this.mSwipeEnabled) {
            return false;
        }
        switch (touchEvent.getAction()) {
            case TouchEvent.POINT_MOVE:
                final int pointerIndex = touchEvent.getPointerCount();
                System.out.println("pointerIndex>>>>>>" + pointerIndex);
                if (pointerIndex == -1 || pointerIndex > 1) {
                    break;
                }
//
                final MmiPoint mmiPoint = touchEvent.getPointerScreenPosition(pointerIndex - 1);

                if (!this.mIsBeingDragged && mInterceptInitX < mEdgeSize) {

                    final int activePointerId = touchEvent.getPointerId(0);
                    if (activePointerId == INVALID_POINTER) {
                        break;
                    }

                    final int xDiff = (int) Math.abs(mmiPoint.getX() - mLastMotionX);
                    if (xDiff > mTouchSlop) {
                        mLastMotionX = (int) mmiPoint.getX();
                        startDragIfNeeded(touchEvent);
                    }
                }

                if (this.mIsBeingDragged) {
                    this.mCallback.onProgress(Math.max(0, mmiPoint.getX() - this.mInitRawX) / ((float) getWidth() - this.mInitRawX));
                }
                break;
            case TouchEvent.PRIMARY_POINT_UP:
            case TouchEvent.PRIMARY_POINT_DOWN:
                finishSwipeGesture();
                return true;

        }
        return true;
    }

    private void finishSwipeGesture() {
        if (this.mIsBeingDragged) {
            this.mCallback.onFinish();
            this.mIsBeingDragged = false;
        }
        this.mActivePointerId = INVALID_POINTER;
        this.mSkipUntilNextGestureEvent = false;
    }

    private void startDragIfNeeded(TouchEvent event) {
        if (this.mIsBeingDragged) {
            return;
        }
        this.mIsBeingDragged = true;
        this.mCallback.onStart();

        final MmiPoint mmiPoint = event.getPointerScreenPosition(event.getIndex());
        this.mInitRawX = mmiPoint.getX();
    }

    public void setEdgeSize(int edgeSize) {
        this.mEdgeSize = edgeSize;
    }

    public void setSwipeEnabled(boolean enabled) {
        if (this.mSwipeEnabled == enabled) {
            return;
        }
        this.mSwipeEnabled = enabled;
        if (!this.mSwipeEnabled && this.mIsBeingDragged) {
            finishSwipeGesture();
        }
    }
}
